package com.hansheng.dao.impl;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;

/**
 * Created by GoldenMan on 2016/12/15.
 */
public class BaseDao<T> {

    private SessionFactory sessionFactory;

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Session getSession() {
        return sessionFactory.getCurrentSession();
    }

    protected void setQueryParams(Query query, Object[] queryParams) {
        if (queryParams != null && queryParams.length > 0) {
            for (int i = 0; i < queryParams.length; i++) {
                query.setParameter(i, queryParams[i]);
            }
        }
    }

    /**
     * @param t 传入实例
     * @return
     */
    @Transactional
    public boolean saveEntity(T t) {
        try {
            getSession().save(t);
            return true;
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @param t 传入实例
     * @return
     */
    @Transactional
    public boolean updateEntity(T t) {
        try {
            getSession().update(t);
            return true;
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @param t 传入实例
     * @return
     */
    @Transactional
    public boolean deleteEntity(T t) {
        try {
            getSession().delete(t);
            return true;
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @param entityClass 实例类名
     * @param id          主键
     * @return
     */
    @Transactional
    public boolean deleteEntityById(Class<T> entityClass, Serializable id) {
        try {
            getSession().delete(getEntity(entityClass, id));
            return true;
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @param entityClass 实例类名
     * @param id          主键
     * @return
     */
    @Transactional
    public T getEntity(Class<T> entityClass, Serializable id) {
        T t = null;
        try {
            t = (T) getSession().get(entityClass, id);
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 更新实体
     *
     * @param t
     */
    public boolean update(T t) {
        try {
            getSession().update(t);
            return true;
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @param entityClass 实例类名
     * @return
     */
    @Transactional
    public List<T> getEntityList(Class<T> entityClass) {
        String hql = "from " + entityClass.getSimpleName();
        List<T> list = null;
        try {
            list = (List<T>) getSession().createQuery(hql).list();
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * @param entityClass 传入实例类
     * @param whereHql    条件语句，其中类的别名使用o（小写字母O）
     * @param params      参数列表
     * @return
     */
    @Transactional
    public T getEntityByCondition(Class<T> entityClass, String whereHql, Object[] params) {
        T t = null;
        try {
            Query query = getSession().createQuery("from " + entityClass.getSimpleName() + " o " + (StringUtils.isBlank(whereHql) ? "" : whereHql));
            setQueryParams(query, params);
            t = (T) query.uniqueResult();
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * @param entityClass 传入实体类
     * @param whereHql    条件语句
     * @param params      参数列表
     * @return
     */
    @Transactional
    public List<T> getEntityListByCondition(Class<T> entityClass, String whereHql, Object[] params) {
        List<T> list = null;
        try {
            Query query = getSession().createQuery("from " + entityClass.getSimpleName() + " o " + (StringUtils.isBlank(whereHql) ? "" : whereHql));
            setQueryParams(query, params);
            list = (List<T>) query.list();
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * @param hql    hql语句
     * @param params 参数列表
     * @return
     */
    @Transactional
    public T[] getEntityByQuery(String hql, Object[] params) {
        T[] t = null;
        try {
            Query query = getSession().createQuery(hql);
            setQueryParams(query, params);
            t = (T[]) query.uniqueResult();
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * @param hql    hql语句
     * @param params 参数列表
     * @return
     */
    @Transactional
    public List<?> getEntityListByQuery(String hql, Object[] params) {
        List<?> list = null;
        try {
            Query query = getSession().createQuery(hql);
            setQueryParams(query, params);
            list = query.list();
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * @param hql    hql语句
     * @param params 参数列表
     * @return
     */
    @Transactional
    public int updateByQuery(String hql, Object[] params) {
            int n = -1;
            try {
                Query query = getSession().createQuery(hql);
                setQueryParams(query, params);
                n = query.executeUpdate();
            } catch (HibernateException e) {
                e.printStackTrace();
            }
        return n;
    }


    /**
     * @param entityClass 实例类类型
     * @param whereHql    where条件语句
     * @param params      参数列表
     * @param firstResult 起始行
     * @param maxResult   每页条数
     * @return
     */
    @Transactional
    public List<T> getEntityListByConditionWithPage(Class<T> entityClass, String whereHql, Object[] params, int firstResult, int maxResult) {
        List<T> list = null;
        try {
            Query query = getSession().createQuery("from " + entityClass.getSimpleName() + " o " + (StringUtils.isBlank(whereHql) ? "" : whereHql));
            setQueryParams(query, params);
            query.setFirstResult(firstResult);
            query.setMaxResults(maxResult);
            list = (List<T>) query.list();
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * @param hql    hql语句
     * @param params 参数列表
     * @return
     */
    @Transactional
    public List<?> getEntityListByQueryWithPage(String hql, Object[] params, int firstResult, int maxResult) {
        List<?> list = null;
        try {
            Query query = getSession().createQuery(hql);
            setQueryParams(query, params);
            query.setFirstResult(firstResult);
            query.setMaxResults(maxResult);
            list = query.list();
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     *
     * @param entityClass   目标表
     * @param whereHql   条件语句
     * @param params    参数列表
     * @return
     */
    @Transactional
    public long getListCountByCondition(Class<T> entityClass ,String whereHql, Object[] params) {
        long count=0;
        try {
            Query query = getSession().createQuery("SELECT count(*) from " + entityClass.getSimpleName() + " o " + (StringUtils.isBlank(whereHql) ? "" : whereHql));
            setQueryParams(query, params);
            Object result=query.uniqueResult();
            count = Integer.parseInt(result.toString());
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return count;
    }

    @Transactional
    public long getListSizeByQuery(String hql, Object[] params) {
        long count=0;
        try {
            Query query = getSession().createQuery(hql);
            setQueryParams(query, params);
            Object result=query.uniqueResult();
            count = Integer.parseInt(result.toString());
        } catch (HibernateException e) {
            e.printStackTrace();
        }
        return count;
    }
}